<template>
  <div class="blogtoc-container" v-if="contents.length">
    <h3>目录</h3>
    <StackContents :list="blogContent" @click="handlerClick" />
  </div>
</template>

<script>
import { StackContents } from ".";
import { debounce } from "@/utils/tools";
export default {
  name: "BlogToc",
  props: {
    contents: {
      type: Array,
      default: () => [],
    },
  },
  components: {
    StackContents,
  },
  created() {
    this.debounceSetActiveAnchor = debounce(this.setActiveAnchor, 80);
    this.$eventBus.$on("mainScroll", this.debounceSetActiveAnchor);
  },
  destroyed() {
    this.$eventBus.$off("mainScroll", this.debounceSetActiveAnchor);
  },
  data() {
    return {
      activeAnchor: "",
    };
  },
  computed: {
    blogContent() {
      const getToc = (toc = []) =>
        toc.map((t) => ({
          ...t,
          isActive: t.anchor == this.activeAnchor,
          children: getToc(t.children),
        }));
      return getToc(this.contents);
    },
    anchorDoms() {
      const doms = [];
      const addToDoms = (toc = []) => {
        toc.forEach((t) => {
          const dom = document.getElementById(t.anchor);
          doms.push(dom);
          addToDoms(t?.children);
        });
      };
      addToDoms(this.contents);
      return doms;
    },
  },
  methods: {
    handlerClick(item) {
      location.hash = item.anchor;
    },
    setActiveAnchor(el_scroll) {
      this.activeAnchor = "";
      const range = 200;
      this.anchorDoms.forEach((dom) => {
        if (!dom) {
          return;
        }
        const { top } = dom.getBoundingClientRect();
        if (top >= 0 && top <= range) {
          this.activeAnchor = dom.id;
          return;
        } else if (top > range) {
          return;
        } else {
          this.activeAnchor = dom.id;
        }
      });
    },
  },
};
</script>

<style scoped lang="less">
.blogtoc-container {
  max-width: 300px;
  box-sizing: border-box;
  padding: 0 10px;
}
</style>
